﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Principal;
using System.Threading;
using System.Web.Mvc;
using AutoMapper;
using DefaultConnection;
using MementoWeb.Controllers;
using MementoWeb.Models;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using PetaPoco;
using MementoLibrary.DTOs;

namespace MementoWeb.Tests.Controllers
{
    [TestClass]
    public class WorkLogControllerTest
    {
        private Mock<IDataRepository> _dataRepository;
        private IList<WorkLog> _workLogs = null;
        private WorkLogController _controller = null;

        [TestInitialize]
        public void Setup()
        {
            AutomapperConfig.RegisterAutomapperMaps();
            _dataRepository = new Mock<IDataRepository>();
            _workLogs = new List<WorkLog>
                            {
                            new WorkLog
                                {
                                    CreatedBy = "test", 
                                    DateCreated = DateTime.Now, 
                                    Description = "", 
                                    DateUpdated = DateTime.Now,
                                    Minutes = 60,
                                    Name = "Development",
                                    PersonId = 1,
                                    TaskId = 1,
                                    UpdatedBy = "test",
                                    Workdate = DateTime.Now,
                                    WorkLogId = 0
                                },
                            new WorkLog
                                {
                                    
                                    CreatedBy = "test", 
                                    DateCreated = DateTime.Now, 
                                    Description = "", 
                                    DateUpdated = DateTime.Now,
                                    Minutes = 30,
                                    Name = "Design",
                                    PersonId = 2,
                                    TaskId = 2,
                                    UpdatedBy = "test",
                                    Workdate = DateTime.Now,
                                    WorkLogId = 1
                                }
                            };
        }


        [TestMethod]
        public void Get()
        {
            // Arrange
            _dataRepository.Setup(r => r.GetAllWorkLogs()).Returns(_workLogs);
            _controller = new WorkLogController(_dataRepository.Object);
            // Act
            var result = _controller.Get();

            // Assert
            Assert.IsNotNull(result);
            _dataRepository.Verify(r => r.GetAllWorkLogs(), Times.AtLeastOnce());
        }

        [TestMethod]
        public void GetWorkLogById()
        {
            const int id = 1;
            _dataRepository.Setup(r => r.GetWorkLogById(id)).Returns(_workLogs[id]);
            _controller = new WorkLogController(_dataRepository.Object);
            var result = _controller.GetById(id);
            Assert.IsNotNull(result);
            _dataRepository.Verify(r => r.GetWorkLogById(id), Times.AtLeastOnce());
        }

        [TestMethod]
        public void CreateNew()
        {
            var controller = new WorkLogController(_dataRepository.Object);
            var workDate = DateTime.Now;
            var project = new ProjectDTO {
                Name = "ProjectName",
                Description = "Description",
                SourceSystem = "TFS100"
            };
            var task = new TaskDTO
            {
                Name = "DoWork",
                Description = "",
                Project = project
            };
            var workLog = new WorkLogDTO
                              {
                                  Minutes = 120,
                                  Workdate = workDate,
                                  WorkLogId = 3,
                                  Task = task
                              };
            var workLogSaved = new WorkLog();
            _dataRepository.Setup(i => i.CreateNewWorkLog(It.IsAny<WorkLog>()))
                .Callback<WorkLog>(w => workLogSaved = w);
            _dataRepository.Setup(w => w.CreateOrUpdateProject(project)).Returns(10);
            _dataRepository.Setup(w => w.CreateOrUpdateTask(task, 10)).Returns(20);
            controller.Post(workLog);
            _dataRepository.VerifyAll();
            
            Assert.AreEqual(workLog.Workdate, workLogSaved.Workdate);
            Assert.AreEqual(20, workLogSaved.TaskId);
            
        }

        [TestMethod]
        public void Update()
        {
            Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("name"), new string[] {});
            const int id = 1;
            const string newWorkLogName = "Updated work log";
            _dataRepository.Setup(r => r.GetWorkLogById(id)).Returns(_workLogs[id]);
            _dataRepository.Setup(r => r.GetOrCreatePersonId("name")).Returns(2);
            _controller = new WorkLogController(_dataRepository.Object);
            var workLog = _controller.GetById(id);
            workLog.Name = newWorkLogName;
            var workLogDTO = Mapper.Map<WorkLogDTO>(workLog);
            var task = workLogDTO.Task = new TaskDTO();
            var project = workLogDTO.Task.Project = new ProjectDTO();
            _dataRepository.Setup(d => d.CreateOrUpdateProject(project)).Returns(5);
            _dataRepository.Setup(d => d.CreateOrUpdateTask(task, 5)).Returns(10);

            _controller.Put(workLogDTO);
            _dataRepository.Verify(r => r.SaveWorkLogChanges(workLog));
            workLog = _controller.GetById(id);
            Assert.AreEqual(workLog.Name, newWorkLogName, "Work Log Update Success");
            _dataRepository.VerifyAll();
        }

        [TestMethod]
        public void Delete()
        {
            const int id = 1;
            _dataRepository.Setup(r => r.GetAllWorkLogs()).Returns(_workLogs);
            _controller = new WorkLogController(_dataRepository.Object);
            _controller.Delete(id);
            _dataRepository.Verify(r => r.DeleteWorkLog(id));
            var result = _controller.Get();
        }
    }
}
